Skip to content

feat(server): next-page prefetch cache for paginated SELECT queries#391

Draft
Copilot wants to merge 22 commits intomainfrom
copilot/evaluate-pagination-cache-implementation
Draft

feat(server): next-page prefetch cache for paginated SELECT queries#391
Copilot wants to merge 22 commits intomainfrom
copilot/evaluate-pagination-cache-implementation

Conversation

Copy link
Contributor

Copilot AI commented Mar 17, 2026

  • Fix MySQL/MariaDB and SQL Server tests: getBoolean() for boolean columns
  • Fix DatasourcePropertiesLoader to forward ojp.nextPageCache.* properties to the server
  • Add ojp.nextPageCache.enabled=true to test ojp.properties for client-side demonstration
  • Update all 7 pagination cache integration test Javadocs to describe client-side configuration
  • Update NEXT_PAGE_PREFETCH_CACHE.md — split config reference into server-side and client-side tables; add two-step Quick Start (server + client)
  • Update ojp-server-configuration.md — remove incorrect "no client changes needed" statement; add two-tier model callout
  • Update part2-chapter6-server-configuration.md — rewrite Configuration section as two-step guide (server infra + client per-datasource opt-in); simplify Per-Datasource section
  • CodeQL: 0 alerts
  • Remove separate ojp-server-prefetch-cache CI container — add nextPageCache flags to main server; update all 7 CSV files port 10594 → 1059

📍 Connect Copilot coding agent with Jira, Azure Boards or Linear to delegate work to Copilot in one click without leaving your project management tool.

Copilot AI and others added 2 commits March 17, 2026 08:28
Co-authored-by: rrobetti <7221783+rrobetti@users.noreply.github.com>
…yInternal

Co-authored-by: rrobetti <7221783+rrobetti@users.noreply.github.com>
Copilot AI changed the title [WIP] Evaluate implementation requirements for pagination cache feat(server): next-page prefetch cache for paginated SELECT queries Mar 17, 2026
Copilot AI requested a review from rrobetti March 17, 2026 08:38
@rrobetti
Copy link
Contributor

@copilot what can we do about these limitations?
CLOB/NCLOB columns: prefetch is skipped; falls back to live query transparently.
LOB parameters (BLOB/CLOB as ? bind values): prefetch skipped — LOB references are session-scoped and cannot be reused on a separate prefetch connection.

Ideally we should be able to cache any type of data including LOB types. Can we not keep them in memory as well ? It might ok to skip queries that receive a LOB as parameter, but as a return type in a query we should be able to cache it.

Co-authored-by: rrobetti <7221783+rrobetti@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Mar 17, 2026

@copilot what can we do about these limitations?
CLOB/NCLOB columns: prefetch is skipped; falls back to live query transparently.
LOB parameters (BLOB/CLOB as ? bind values): prefe...

Done in commit 563e3f8. CLOB/NCLOB (and LONGVARCHAR/LONGNVARCHAR) return columns are now fully cached — the character stream is read eagerly via getCharacterStream() / getNCharacterStream() and materialised as a String (identical to how BLOBs are materialised as byte[]). Readers are properly closed via try-with-resources.

The only remaining skip is for queries that pass LOB session references as input parameters (BLOB/CLOB ? bind values) — those are session-scoped objects that cannot be transferred to a separate prefetch connection.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • 999.999.999.999
    • Triggering command: /usr/lib/jvm/temurin-21-jdk-amd64/bin/java /usr/lib/jvm/temurin-21-jdk-amd64/bin/java -jar /home/REDACTED/work/ojp/ojp/ojp-server/target/surefire/surefirebooter-20260317122409043_3.jar /home/REDACTED/work/ojp/ojp/ojp-server/target/surefire 2026-03-17T12-24-08_980-jvmRun1 surefire-20260317122409043_1tmp surefire_0-20260317122409043_2tmp (dns block)
    • Triggering command: /usr/lib/jvm/temurin-21-jdk-amd64/bin/java /usr/lib/jvm/temurin-21-jdk-amd64/bin/java -jar /home/REDACTED/work/ojp/ojp/ojp-server/target/surefire/surefirebooter-20260317122533717_3.jar /home/REDACTED/work/ojp/ojp/ojp-server/target/surefire 2026-03-17T12-25-33_648-jvmRun1 surefire-20260317122533717_1tmp surefire_0-20260317122533717_2tmp (dns block)
  • invalid-ip
    • Triggering command: /usr/lib/jvm/temurin-21-jdk-amd64/bin/java /usr/lib/jvm/temurin-21-jdk-amd64/bin/java -jar /home/REDACTED/work/ojp/ojp/ojp-server/target/surefire/surefirebooter-20260317122409043_3.jar /home/REDACTED/work/ojp/ojp/ojp-server/target/surefire 2026-03-17T12-24-08_980-jvmRun1 surefire-20260317122409043_1tmp surefire_0-20260317122409043_2tmp (dns block)
    • Triggering command: /usr/lib/jvm/temurin-21-jdk-amd64/bin/java /usr/lib/jvm/temurin-21-jdk-amd64/bin/java -jar /home/REDACTED/work/ojp/ojp/ojp-server/target/surefire/surefirebooter-20260317122533717_3.jar /home/REDACTED/work/ojp/ojp/ojp-server/target/surefire 2026-03-17T12-25-33_648-jvmRun1 surefire-20260317122533717_1tmp surefire_0-20260317122533717_2tmp (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

@rrobetti
Copy link
Contributor

@copilot some questions in relation to this implementation:
1 - Is cache isolated by datasource? meaning if to datasources share the same query they don't get the wrong cached data.
2 - Is there a job to clean up abandoned cached pages? We need a configuration that can set how long a cache can be held before being cleaned up, default it to 60 seconds.

…-page prefetch cache

Co-authored-by: rrobetti <7221783+rrobetti@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Mar 17, 2026

@copilot some questions in relation to this implementation:
1 - Is cache isolated by datasource? meaning if to datasources share the same query they don't get the wrong cached data....

Both addressed in commit 77195b9:

1 - Cache isolation by datasource: Yes, it's now fully isolated. The cache key is datasourceId \u0001 normalizedSql — the SOH control character (\u0001) is used as separator since it cannot appear in SQL text or a connection hash, preventing any key collision. Two datasources running the same query get completely independent cache entries.

2 - Background cleanup job: A daemon ScheduledExecutorService thread now runs evictExpiredOrCompleted() on a configurable interval (default 60 seconds). The new config property is ojp.server.nextPageCache.cleanupIntervalSeconds (defaults to 60). The default TTL (ojp.server.nextPageCache.ttlSeconds) is also reduced from 300s to 60s to align with the recommended hold time. The cache implements AutoCloseable and exposes shutdown() to stop the scheduler cleanly.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • 999.999.999.999
    • Triggering command: /usr/lib/jvm/temurin-21-jdk-amd64/bin/java /usr/lib/jvm/temurin-21-jdk-amd64/bin/java -jar /home/REDACTED/work/ojp/ojp/ojp-server/target/surefire/surefirebooter-20260317125234018_3.jar /home/REDACTED/work/ojp/ojp/ojp-server/target/surefire 2026-03-17T12-52-33_945-jvmRun1 surefire-20260317125234018_1tmp surefire_0-20260317125234018_2tmp (dns block)
    • Triggering command: /usr/lib/jvm/temurin-21-jdk-amd64/bin/java /usr/lib/jvm/temurin-21-jdk-amd64/bin/java -jar /home/REDACTED/work/ojp/ojp/ojp-server/target/surefire/surefirebooter-20260317125505274_3.jar /home/REDACTED/work/ojp/ojp/ojp-server/target/surefire 2026-03-17T12-55-05_196-jvmRun1 surefire-20260317125505274_1tmp surefire_0-20260317125505274_2tmp (dns block)
  • invalid-ip
    • Triggering command: /usr/lib/jvm/temurin-21-jdk-amd64/bin/java /usr/lib/jvm/temurin-21-jdk-amd64/bin/java -jar /home/REDACTED/work/ojp/ojp/ojp-server/target/surefire/surefirebooter-20260317125234018_3.jar /home/REDACTED/work/ojp/ojp/ojp-server/target/surefire 2026-03-17T12-52-33_945-jvmRun1 surefire-20260317125234018_1tmp surefire_0-20260317125234018_2tmp (dns block)
    • Triggering command: /usr/lib/jvm/temurin-21-jdk-amd64/bin/java /usr/lib/jvm/temurin-21-jdk-amd64/bin/java -jar /home/REDACTED/work/ojp/ojp/ojp-server/target/surefire/surefirebooter-20260317125505274_3.jar /home/REDACTED/work/ojp/ojp/ojp-server/target/surefire 2026-03-17T12-55-05_196-jvmRun1 surefire-20260317125505274_1tmp surefire_0-20260317125505274_2tmp (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

@rrobetti
Copy link
Contributor

@copilot make sure there is only one background job that checks all cached objects, there is no need for multiple threads cleaning.

…thread across all cache instances

Co-authored-by: rrobetti <7221783+rrobetti@users.noreply.github.com>
@rrobetti
Copy link
Contributor

@copilot create an integration test for Postgres with pagination. The test should create different amounts of records (99, 100, 101, 567(random), 1000 - make sure you use parameterized tests, not duplications) in a given table that contains multiple types and at least one LOB type. There should be tests paginating 100 records per page. You have to run a separate OJP server in the main CI workflow on a different port with pagination cache enabled and point the new integration test at this new server. You can use the same postgres db already present in the workflow, just name the table uniquely. Make sure all records are returned correctly when using cache and pagination, and assert every value. If a lob makes sure all bytes are returned correctly.
Let me know of your questions, concerns, suggestions, and opinions.

Copy link
Contributor Author

Copilot AI commented Mar 17, 2026

@copilot make sure there is only one background job that checks all cached objects, there is no need for multiple threads cleaning.

Done in commit 268cdaa. The ScheduledExecutorService is now a static final field (CLEANUP_EXECUTOR) shared across all NextPagePrefetchCache instances — exactly one background thread exists per JVM regardless of how many instances are created. Each instance holds only an AtomicReference<ScheduledFuture<?>> to track and cancel its own eviction task independently without touching the shared executor or affecting other instances. shutdown() uses AtomicReference.getAndSet(null) to atomically swap the task handle out, avoiding concurrent double-cancel races.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • 999.999.999.999
    • Triggering command: /usr/lib/jvm/temurin-21-jdk-amd64/bin/java /usr/lib/jvm/temurin-21-jdk-amd64/bin/java -jar /home/REDACTED/work/ojp/ojp/ojp-server/target/surefire/surefirebooter-20260317180556011_3.jar /home/REDACTED/work/ojp/ojp/ojp-server/target/surefire 2026-03-17T18-05-55_941-jvmRun1 surefire-20260317180556011_1tmp surefire_0-20260317180556011_2tmp (dns block)
  • invalid-ip
    • Triggering command: /usr/lib/jvm/temurin-21-jdk-amd64/bin/java /usr/lib/jvm/temurin-21-jdk-amd64/bin/java -jar /home/REDACTED/work/ojp/ojp/ojp-server/target/surefire/surefirebooter-20260317180556011_3.jar /home/REDACTED/work/ojp/ojp/ojp-server/target/surefire 2026-03-17T18-05-55_941-jvmRun1 surefire-20260317180556011_1tmp surefire_0-20260317180556011_2tmp (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

… assertion

Co-authored-by: rrobetti <7221783+rrobetti@users.noreply.github.com>
Copy link
Contributor

@rrobetti rrobetti left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot create a mermaid flow diagram explaining in simple terms how the caching works and how the clean up job works.

*/
private static final ScheduledExecutorService CLEANUP_EXECUTOR =
Executors.newSingleThreadScheduledExecutor(r -> {
Thread t = new Thread(r, "ojp-prefetch-cache-cleanup");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot this should be a virtual thread.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in commit 73a4d18. The thread factory now uses Thread.ofVirtual().name("ojp-prefetch-cache-cleanup").unstarted(r) instead of new Thread(r, ...). The explicit setDaemon(true) is no longer needed since virtual threads are always daemon threads. All 434 tests pass.

Copy link
Contributor Author

Copilot AI commented Mar 17, 2026

@copilot create an integration test for Postgres with pagination. The test should create different amounts of records (99, 100, 101, 567(random), 1000 - make sure you use parameterized tests, not dupl...

Done in commit e953c30.

New test classPostgresPaginationCacheIntegrationTest:

  • Parameterized over 5 record counts: 99, 100, 101, 567, 1000 (via postgres_prefetch_cache_connections_with_record_counts.csv), covering partial-page, exact-page, one-over, non-round, and 10-page scenarios
  • Table ojp_pfx_pg_{recordCount} has 7 columns of varied types: INT, BIGINT, BOOLEAN, VARCHAR(100), TEXT, and BYTEA (LOB)
  • Rows are inserted with fully deterministic per-row values via a PreparedStatement batch
  • Paginates with LIMIT 100 OFFSET ? (ORDER BY id) and asserts every column value on every row, including a byte-exact comparison of the BYTEA column — handles both byte[] and PostgreSQL hex-escape string representations (\xHH…)
  • Enabled only with -DenablePostgresPrefetchCacheTests=true; skips automatically otherwise

CI workflowpostgres-test job:

  • Starts a third OJP server container ojp-server-prefetch-cache on port 10594 with ojp.server.nextPageCache.enabled=true, ttlSeconds=60, prefetchWaitTimeoutMs=5000
  • Passes -DenablePostgresPrefetchCacheTests=true in the existing "Test (ojp-jdbc-driver) with PostgreSQL enabled" step
  • Logs from the new container are captured in the always-run log step

Concern/note: PostgreSQL does not have a native BLOB/CLOB type — its binary LOB is BYTEA. The prefetch cache materialises BYTEA as byte[] (via rs.getBytes() for Types.BINARY/VARBINARY), which is then serialised as ByteString over gRPC and returned to the client as byte[]. The test verifies this round-trip byte-for-byte.

Copilot AI requested a review from rrobetti March 17, 2026 18:29
…extPageCache.enabled)

Co-authored-by: rrobetti <7221783+rrobetti@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Mar 18, 2026

@copilot why do we need any configuration on the server?

You're right — there's no need for server-side per-datasource configuration for enabled. The server owns the global toggle (ojp.server.nextPageCache.enabled); whether a specific datasource in a client application uses the cache is the client's concern.

Fixed in 37a84bf. The per-datasource enabled flag is now a client-side connection property:

# ojp.properties — client application
# Disable the prefetch cache for the "random-access" datasource
random-access.ojp.nextPageCache.enabled=false

The server reads ojp.nextPageCache.enabled from the ConnectionDetails properties sent on connect() and registers it per connection. When the property is absent, the global server flag applies as the default. The ojp.server.nextPageCache.datasource.<name>.enabled server property and its tests have been removed.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • 999.999.999.999
    • Triggering command: /usr/lib/jvm/temurin-21-jdk-amd64/bin/java /usr/lib/jvm/temurin-21-jdk-amd64/bin/java -jar /home/REDACTED/work/ojp/ojp/ojp-server/target/surefire/surefirebooter-20260318090040804_3.jar /home/REDACTED/work/ojp/ojp/ojp-server/target/surefire 2026-03-18T09-00-40_730-jvmRun1 surefire-20260318090040804_1tmp surefire_0-20260318090040804_2tmp (dns block)
  • invalid-ip
    • Triggering command: /usr/lib/jvm/temurin-21-jdk-amd64/bin/java /usr/lib/jvm/temurin-21-jdk-amd64/bin/java -jar /home/REDACTED/work/ojp/ojp/ojp-server/target/surefire/surefirebooter-20260318090040804_3.jar /home/REDACTED/work/ojp/ojp/ojp-server/target/surefire 2026-03-18T09-00-40_730-jvmRun1 surefire-20260318090040804_1tmp surefire_0-20260318090040804_2tmp (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

@rrobetti
Copy link
Contributor

@copilot implement similar pagination integration tests for all other databases supported.

…achDB, DB2, Oracle, SQL Server, and H2

Co-authored-by: rrobetti <7221783+rrobetti@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Mar 18, 2026

@copilot implement similar pagination integration tests for all other databases supported.

Done in 065b101. Pagination cache integration tests now cover all supported databases:

Database Test class Pagination syntax Binary column
MySQL MySQLMariaDBPaginationCacheIntegrationTest LIMIT n OFFSET m VARBINARY(32)
MariaDB same class LIMIT n OFFSET m VARBINARY(32)
CockroachDB CockroachDBPaginationCacheIntegrationTest LIMIT n OFFSET m BYTEA
DB2 Db2PaginationCacheIntegrationTest OFFSET m ROWS FETCH NEXT n ROWS ONLY BLOB(1K)
Oracle OraclePaginationCacheIntegrationTest OFFSET m ROWS FETCH NEXT n ROWS ONLY BLOB
SQL Server SQLServerPaginationCacheIntegrationTest OFFSET m ROWS FETCH NEXT n ROWS ONLY VARBINARY(32)
H2 H2PaginationCacheIntegrationTest LIMIT n OFFSET m VARBINARY(32)

Each test paginates over 5 record counts (99, 100, 101, 567, 1000), asserts every column including byte-exact binary comparison, and is disabled by default (enabled via enable{DB}PrefetchCacheTests=true). The CI workflow was updated to start a second OJP server with the prefetch cache enabled (port 10594) for each database job.

@rrobetti
Copy link
Contributor

@copilot

Tests failing

MySQL and MariaDB

Error: Errors:
Error: MySQLMariaDBPaginationCacheIntegrationTest.testMariaDBPaginationWithPrefetchCache:91->runPaginationTest:116->assertPage:212 » NumberFormat For input string: "false"
Error: MySQLMariaDBPaginationCacheIntegrationTest.testMariaDBPaginationWithPrefetchCache:91->runPaginationTest:116->assertPage:212 » NumberFormat For input string: "false"
Error: MySQLMariaDBPaginationCacheIntegrationTest.testMariaDBPaginationWithPrefetchCache:91->runPaginationTest:116->assertPage:212 » NumberFormat For input string: "false"
Error: MySQLMariaDBPaginationCacheIntegrationTest.testMariaDBPaginationWithPrefetchCache:91->runPaginationTest:116->assertPage:212 » NumberFormat For input string: "false"
Error: MySQLMariaDBPaginationCacheIntegrationTest.testMariaDBPaginationWithPrefetchCache:91->runPaginationTest:116->assertPage:212 » NumberFormat For input string: "false"

SQL server

logs have errors like this
[main] ERROR org.openjproxy.jdbc.Driver - Failed to establish connection
java.sql.SQLException: Failed to create datasource: Failed to create HikariCP DataSource: Failed to initialize pool: The TCP/IP connection to the host localhost, port 1433 has failed. Error: "Connection refused. Verify the connection properties. Make sure that an instance of SQL Server is running on the host and accepting TCP/IP connections at the port. Make sure that TCP connections to the port are not blocked by a firewall.".
at org.openjproxy.grpc.client.GrpcExceptionHandler.handle(GrpcExceptionHandler.java:32)
at org.openjproxy.grpc.client.StatementServiceGrpcClient.connect(StatementServiceGrpcClient.java:64)
at org.openjproxy.jdbc.Driver.connect(Driver.java:111)
at java.sql/java.sql.DriverManager.getConnection(DriverManager.java:677)
at java.sql/java.sql.DriverManager.getConnection(DriverManager.java:228)

tests are failing

Error: Errors:
Error: SQLServerPaginationCacheIntegrationTest.testPaginationWithPrefetchCache:109->assertPage:228 » NumberFormat For input string: "false"
Error: SQLServerPaginationCacheIntegrationTest.testPaginationWithPrefetchCache:109->assertPage:228 » NumberFormat For input string: "false"
Error: SQLServerPaginationCacheIntegrationTest.testPaginationWithPrefetchCache:109->assertPage:228 » NumberFormat For input string: "false"
Error: SQLServerPaginationCacheIntegrationTest.testPaginationWithPrefetchCache:109->assertPage:228 » NumberFormat For input string: "false"
Error: SQLServerPaginationCacheIntegrationTest.testPaginationWithPrefetchCache:109->assertPage:228 » NumberFormat For input string: "false"

…ache tests

MariaDB TINYINT(1) and SQL Server BIT are both mapped to Java Boolean by
their JDBC drivers. Calling rs.getInt() on these columns threw
NumberFormatException("false"). Changed both tests to use getBoolean()
with `id % 2 == 0`, consistent with PostgreSQL/H2/CockroachDB tests.

Co-authored-by: rrobetti <7221783+rrobetti@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Mar 18, 2026

@copilot

Tests failing
...

Fixed in d7cf13c.

MySQL/MariaDB: MariaDB's TINYINT(1) is mapped to Java Boolean by the MariaDB Connector/J driver. When read via rs.getInt("val_bool"), the client received the string "false" and threw NumberFormatException. Fixed by switching to rs.getBoolean("val_bool") with comparison id % 2 == 0 — consistent with the PostgreSQL, H2, and CockroachDB tests that already used getBoolean().

SQL Server: SQL Server's BIT type is also mapped to Boolean by the MSSQL JDBC driver, so rs.getInt("val_bool") would fail the same way. Applied the same fix (getBoolean() + id % 2 == 0).

Copy link
Contributor

@rrobetti rrobetti left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update the documentation as per now the configurations are in the client side instead of the server. Make sure that is the case on the integration tests.

…docs and tests for client-side config

Co-authored-by: rrobetti <7221783+rrobetti@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Mar 19, 2026

Update the documentation as per now the configurations are in the client side instead of the server. Make sure that is the case on the integration tests.

Fixed in 4ba9354:

Root cause of the gap: DatasourcePropertiesLoader only forwarded ojp.connection.pool.* and ojp.xa.* keys to the server — ojp.nextPageCache.* properties were silently dropped, so the client-side enabled flag was never actually sent.

Changes:

  • DatasourcePropertiesLoader: added OJP_NEXT_PAGE_CACHE_PREFIX = "ojp.nextPageCache." so all ojp.nextPageCache.* properties (including ojp.nextPageCache.enabled and per-datasource variants like reporting.ojp.nextPageCache.enabled) are now forwarded to the server at connect time.
  • Test ojp.properties: added ojp.nextPageCache.enabled=true so the integration tests explicitly opt in via the client-side property.
  • All 7 pagination cache integration test Javadocs updated to describe both the server-side global flag (ojp.server.nextPageCache.enabled=true) and the client-side per-datasource flag (ojp.nextPageCache.enabled=true in ojp.properties).
  • Docs (NEXT_PAGE_PREFETCH_CACHE.md, ojp-server-configuration.md, part2-chapter6-server-configuration.md): split config reference tables into server-side and client-side sections; expanded examples to show both opt-in and opt-out per datasource.

Copilot AI requested a review from rrobetti March 19, 2026 07:58
rrobetti/ojp:0.4.1-SNAPSHOT

# Pagination-cache integration tests run against this server (port 10594)
- name: Start OJP Server container (prefetch cache on port 10594)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we still need a separated ojp server if now the nextPageCache is enabled in the client side per datasource?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No — the separate server is no longer needed. Since the cache opt-in is now a client-side property (ojp.nextPageCache.enabled), the main OJP server is all that's needed. Fixed in 3a93056: the nextPageCache flags (enabled, ttlSeconds, prefetchWaitTimeoutMs) are moved to the main server in all 8 CI jobs, the ojp-server-prefetch-cache container is removed, and all 7 pagination-cache CSV files are updated from port 105941059.


# Start third OJP server WITH next-page prefetch cache enabled
# Pagination-cache integration tests run against this server (port 10594)
- name: Start OJP Server container (prefetch cache on port 10594)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need a separated ojp server if nextPageCache is not enabled in the client side?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No — a separate server is no longer needed. The main server has ojp.server.nextPageCache.enabled=true globally, and each client datasource opts in or out via ojp.nextPageCache.enabled in ojp.properties. The ojp-server-prefetch-cache container (port 10594) has been removed in 3a93056.

…e CSV ports and test docs

Co-authored-by: rrobetti <7221783+rrobetti@users.noreply.github.com>
Copilot AI requested a review from rrobetti March 19, 2026 09:27

| Property | Default | Description |
|---|---|---|
| `ojp.server.nextPageCache.enabled` | `false` | Enable/disable the feature globally |
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is this still talking about ojp.server configs, configs are no longer in the server, why dont you update everyhing? Review all changes in this PR and update

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in c0da110. All three documentation files have been updated to clearly reflect the two-tier model:

  • part2-chapter6-server-configuration.md: The "Configuration" section is rewritten as a two-step guide — Step 1 (server admin enables infra via ojp.server.nextPageCache.enabled=true) and Step 2 (client app opts each datasource in/out via ojp.nextPageCache.enabled in ojp.properties). The "Per-Datasource Cache Control" subsection now only covers the server-side prefetchWaitTimeoutMs per-datasource override (the only server setting that is still per-datasource).

  • ojp-server-configuration.md: Removed the incorrect "No client changes are needed — the feature is entirely transparent" statement. Added a "Two-tier configuration model" callout box explaining the server/client split.

  • NEXT_PAGE_PREFETCH_CACHE.md: "Quick Start" is now a two-step guide showing both server startup and the client ojp.properties configuration.

The server still owns the global toggle and resource tuning (ttlSeconds, maxEntries, etc.) — these affect server memory. The per-datasource enabled flag lives entirely on the client side.

…ss all three docs

Co-authored-by: rrobetti <7221783+rrobetti@users.noreply.github.com>
@sonarqubecloud
Copy link

Copilot AI requested a review from rrobetti March 19, 2026 09:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants